package com.fingard.dsp.bank.directbank.spdb01;

import com.fingard.constant.Format;
import com.fingard.dsp.bank.directConfig.ActSetItem;
import com.fingard.dsp.bank.directbank.FailCode;
import com.fingard.dsp.bank.directbank.PaymentState;
import com.fingard.dsp.bank.directbank.bankInterface.IRealTime;
import com.fingard.dsp.bank.directbank.spdb01.authforrec.SecurityAES;
import com.fingard.dsp.bank.directbank.spdb01.authforrec.StringUtils;
import com.fingard.dsp.bank.directbank.spdb01.authforrec.XMLGetValueHelper;
import com.fingard.dsp.bank.reqrespobj.single.ReqQrySingle;
import com.fingard.dsp.bank.reqrespobj.single.ReqSingle;
import com.fingard.dsp.bank.reqrespobj.single.RetAtsSingle;
import com.fingard.dsp.bank.reqrespobj.single.detail.ReqPayRecDetail;
import com.fingard.dsp.bank.reqrespobj.single.detail.RetAtsSglDetail;
import com.fingard.dsp.basicbankdata.ebank.EBankData;
import com.fingard.text.StringHelper;
import com.fingard.xml.XElement;
import com.fingard.xml.XmlTextReader;
import com.fingard.xml.XmlTextWriter;

/**
 * @author Cruise
 * @date 2019/4/23
 */
public class SPDB01RealTime extends SPDB01Base implements IRealTime {
    @Override
    public RetAtsSingle d_9108_RealTimeRec(ReqSingle p_req9108) throws Exception {
        RetAtsSingle retAts = new RetAtsSingle(p_req9108.reqHeader);
        
        RetAtsSglDetail tmpRetDetail = null;
        if ("910802".equals(p_req9108.reqHeader.commandCode)) {
        	tmpRetDetail = oldRealTimePayRec(p_req9108);
        } else {
        	tmpRetDetail = realTimePayRec(p_req9108);
        }
        retAts.writeRetDetail(tmpRetDetail);
        return retAts;
    }
    
    public RetAtsSglDetail oldRealTimePayRec(ReqSingle p_req9108) throws Exception {
		RetAtsSglDetail tmpRetDetail = new RetAtsSglDetail();
		tmpRetDetail.reqSeqID = p_req9108.singleDetail.askNumber;
		
		try {
			ActSetItem actItem = getBankConfig().getActSetItem(p_req9108.singleDetail.recAct, "");
			if (actItem == null) {
				tmpRetDetail.respCode = "0";
				tmpRetDetail.respInfo = "未找到账号[" + p_req9108.singleDetail.recAct + "]批量商户配置信息";
				tmpRetDetail.reqSeqID = p_req9108.singleDetail.askNumber;
				tmpRetDetail.transState = PaymentState.FAIL_Payment;
				tmpRetDetail.payInfoCode = FailCode.E9981;
				return tmpRetDetail;
			} 
			
			getSessionKey(actItem);
			
			XmlTextWriter xmlWriter = new XmlTextWriter();
            xmlWriter.writeStartDocByDeclaration("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
            xmlWriter.writeStartElement("Message");
            xmlWriter.writeStartElement("Head");
            xmlWriter.writeElementString("TransCode", "01");
            xmlWriter.writeElementString("CorpNo", actItem.corpCode);
            xmlWriter.writeElementString("TransType", "1");
            xmlWriter.writeElementString("FeeNo", actItem.busCode);
            xmlWriter.writeEndElement();
            xmlWriter.writeStartElement("Body");
            if ("1".equals(p_req9108.singleDetail.sameBnk)) {
                xmlWriter.writeElementString("BankType", "0");
            } else {
                xmlWriter.writeElementString("BankType", "1");
            }
            xmlWriter.writeElementString("ChannelNo", "82");
            xmlWriter.writeElementString("PayAmt", StringHelper.amountMultiply100(p_req9108.singleDetail.payAmount));
            xmlWriter.writeElementString("SerialNo", p_req9108.singleDetail.askNumber);
            xmlWriter.writeElementString("DbtrActId", p_req9108.singleDetail.payAct);
            xmlWriter.writeElementString("DbtrActName", p_req9108.singleDetail.payName);
            xmlWriter.writeElementString("DbtrBankId", p_req9108.singleDetail.cnapsCode);
            xmlWriter.writeElementString("DbtrBankName", p_req9108.singleDetail.cnapsName);
            xmlWriter.writeElementString("CustName", "");
            xmlWriter.writeElementString("ProductInfo", "");
            xmlWriter.writeElementString("Remark", p_req9108.singleDetail.memo);
            xmlWriter.writeElementString("Use", "");
            xmlWriter.writeEndDocument();
            String xmlPck = xmlWriter.toXmlString();
            WriteBankLogStep2("发送的明文：" + xmlPck);

            String sessionKey = bankFront.customMap.get("authForRec-sessionKey");
            byte[] bytesToSend = SecurityAES.encrypt(xmlPck, sessionKey);

            String strToSend = StringHelper.bytesToHexString(bytesToSend);
            xmlWriter = null;
            xmlWriter = new XmlTextWriter();
            xmlWriter.writeStartDocByDeclaration("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
            xmlWriter.writeStartElement("Message");
            xmlWriter.writeStartElement("Head");
            xmlWriter.writeElementString("CorpNo", actItem.corpCode);
            xmlWriter.writeElementString("Version", "1.0");
            xmlWriter.writeElementString("ReqTime", bankFront.customMap.get("authForRec-timeStr"));
            xmlWriter.writeEndElement();
            xmlWriter.writeStartElement("Body");
            xmlWriter.writeElementString("ReqData", strToSend);
            xmlWriter.writeEndDocument();

            String pckSend = xmlWriter.toXmlString();

            WriteBankLogStep2("发送的密文：" + pckSend);
            byte[] result = sentBytesToBank(pckSend.getBytes(getCharset("authForRec")));
            
            String resultXml = new String(result);
            WriteBankLogStep3("接收的密文：" + resultXml);
            String xmlContent = XMLGetValueHelper.getInstance(resultXml).getString("ResData");

            xmlContent = SecurityAES.decrypt(StringUtils.hexStringToBytes(xmlContent), sessionKey);
            WriteBankLogStep3("接收的明文：" + xmlContent);

            int idxEnd = xmlContent.indexOf("</Message>");
            if (idxEnd > 0) {
                xmlContent = xmlContent.substring(0, idxEnd + 10);
            }
            XMLGetValueHelper xmlHelper = XMLGetValueHelper.getInstance(xmlContent);
            String ReturnCode = xmlHelper.getString("ReturnCode");
            String ReturnMsg = xmlHelper.getString("ReturnMsg");
            String SignStatus = xmlHelper.getString("Status");
            
            tmpRetDetail.respCode = "0";
            tmpRetDetail.respInfo = ReturnMsg;
            tmpRetDetail.transState = "0+" + SignStatus;
            tmpRetDetail.payInfoCode = ReturnCode;
		} catch (Exception ex) {
			ex.printStackTrace();
			tmpRetDetail.respCode = "-1";
			tmpRetDetail.respInfo = ex.getMessage();
			WriteBankLogLn(ex);
		}
		
        return tmpRetDetail;
    }

    public RetAtsSglDetail realTimePayRec(ReqSingle p_rtReq ) throws Exception {
        ReqPayRecDetail detail = p_rtReq.singleDetail;
        RetAtsSglDetail retDetail = new RetAtsSglDetail();
        SPDB01Header tmpBnkHeader = new SPDB01Header();
        retDetail.reqSeqID = p_rtReq.singleDetail.askNumber;
        tmpBnkHeader.transCode = "AQ49";
        String batchNo = p_rtReq.singleDetail.askNumber;
        String cardtype = "";
        //payeeType 收款人账户类型 0-对公账号  1-卡  8-活期存折
        if ("1".equals(detail.cardType)) {
            cardtype = "8";
        } else {
            cardtype = "1";
        }

        XmlTextWriter xmlWriter = new XmlTextWriter();//发银行报文的XML对象
        String transType = p_rtReq.reqHeader.transType;
        //需要进行对账码拼接以及节点解析，采用XElement进行处理
        xmlWriter.autoFormat = false;
        XElement tmpXElement = new XElement("body", "");

        String ownAct = detail.recAct;
        if ("6908".equals(transType)) {
        	ownAct = detail.payAct;
        }
        
        tmpXElement.addChild(new XElement("transMasterID", getBankConfig().getMapValueByKey("transMasterIDMapping", ownAct)));//交易客户号
        tmpXElement.addChild(new XElement("projectNumber", getBankConfig().getMapValueByKey("projectNumberMapping", ownAct)));//项目编码
        tmpXElement.addChild(new XElement("costItemCode",   getBankConfig().getMapValueByKey("costItemCodeMapping", ownAct)));//费项编码Y
        String type = "1"; //1:代收     2:代付
        if ("6908".equals(transType)) {
            type = "2";
        }
        String oppAct = detail.payAct;
        String oppActNm = detail.payName;
        String oppBankCode = "";
        String oppStandardArea = "";
        if ("6908".equals(transType)) {
            oppAct = detail.recAct;
            oppActNm = detail.recName;
            oppBankCode = detail.recBankCode;
            oppStandardArea = detail.recStandardArea;
        }
        tmpXElement.addChild(new XElement("transTypeCode", type));//交易类型Y

        tmpXElement.addChild(new XElement("elecChequeNo", batchNo));//电子凭证号Y
        tmpXElement.addChild(new XElement("crossLineSign",  "1".equals(detail.sameBnk)?"0":"1"));//0:同行 1:他行
        tmpXElement.addChild(new XElement("onlyChannelFlag", "0"));//是否指定唯一渠道N
        tmpXElement.addChild(new XElement("payChannelNo", ""));//当指定特定渠道时，必须输入
        tmpXElement.addChild(new XElement("adversaryType", "1".equals(detail.isPrivate) ?"1":"0"));//0:对公   1:对私
        tmpXElement.addChild(new XElement("adversaryDocType", ""));//证件N
        tmpXElement.addChild(new XElement("adversaryIDNumber", ""));//对手证件号码N
        tmpXElement.addChild(new XElement("adversaryAccountType", cardtype));//对手账号类型
        tmpXElement.addChild(new XElement("adversaryAccount", oppAct));//对手账号
        tmpXElement.addChild(new XElement("adversaryAccountName", oppActNm));//对手账号户名
        tmpXElement.addChild(new XElement("adversaryBankNo", ""));//收款行行号（浦发内部版）
        tmpXElement.addChild(new XElement("adversaryBankName", ""));//收款行行名
        
        String payBankNo = "";
        String[] ebankCodeName = EBankData.mappingEBankCode(oppBankCode, oppStandardArea);
        if(ebankCodeName!=null && ebankCodeName[0].length()>0){
        	payBankNo = ebankCodeName[0];//收款行行号
        }else{
        	payBankNo = detail.cnapsCode;//收款行行号
        }
        tmpXElement.addChild(new XElement("payBankNo", payBankNo));//收款行行号
        tmpXElement.addChild(new XElement("amount", detail.payAmount));//金额
        tmpXElement.addChild(new XElement("phoneNumber", ""));//手机号
        tmpXElement.addChild(new XElement("note", detail.purpose + "＋" + detail.abstractATS));//摘要
        tmpXElement.addChild(new XElement("purpose", detail.purpose));//用途或附言N
        tmpXElement.addChild(new XElement("note1", ""));//备用字段1N
        tmpXElement.addChild(new XElement("note2", ""));//备用字段2N
        tmpXElement.addChild(new XElement("note3", ""));//备用字段3N

        nodeAnalysis(p_rtReq.singleDetail.srcXElement, tmpXElement, getCharset());
        xmlWriter.writeXElement(tmpXElement);
        xmlWriter.writeEndDocument();//写入报文完成
        String[] tmpStrRet = sendToBank(xmlWriter.toXmlString(), tmpBnkHeader);//发送银行
        if (tmpStrRet[0].length() == 0) {
            StringBuilder tmpSbMsg = new StringBuilder();
            //解析银行返回
            XmlTextReader tmpBkReader = loadBankRespXmlReader(tmpStrRet[1], tmpSbMsg);
            if (tmpBkReader != null) {
                String returnCode = tmpBkReader.getFirstText("/packet/head/returnCode");
                String returnMsg = tmpBkReader.getFirstText("/packet/head/returnMsg");
                if (StringHelper.hasAnyChar(returnCode)) {
                    retDetail.respCode = "0";
                    if (returnMsg == null || "".equals(returnMsg)) {
                        returnMsg = tmpBkReader.getFirstText("/packet/body/returnMsg");
                    }
                    retDetail.respInfo = returnMsg;
                    if ("AAAAAAA".equals(returnCode)) {
                        String handleResult = tmpBkReader.getFirstText("/packet/body/handleResult");
                        //0:成功、
                        //1:失败、
                        //2:处理中
                        retDetail.transState = returnCode + "+" + handleResult;
                        retDetail.payInfoCode = returnCode + "+" + handleResult;
                        retDetail.reqSeqID = tmpBkReader.getFirstText("/packet/body/elecChequeNo");
                        if (retDetail.respInfo==null||"".equals(retDetail.respInfo)) {
                            if ("0".equals(handleResult)) {
                                retDetail.respInfo = "交易成功";
                            } else if("2".equals(handleResult)){
                                retDetail.respInfo = "提交支付中";
                            }
                        }
                    } else {
                        retDetail.transState = returnCode;
                        retDetail.payInfoCode = returnMsg;
                    }
                } else {
                    retDetail.respCode = "-1";
                    if (StringHelper.hasAnyChar(returnMsg)) {
                        retDetail.respInfo = returnMsg;
                    } else {
                        retDetail.respInfo = "returnCode节点为空";
                    }
                }
            } else {
                retDetail.respCode = "-1";
                retDetail.respInfo = tmpSbMsg.toString();
            }
        } else {
            retDetail.respCode = "-1";
            retDetail.respInfo = tmpStrRet[1];
        }

        return retDetail;
    }

    @Override
    public RetAtsSingle d_9144_QryRealTimeRec(ReqQrySingle p_req9144) throws Exception {
    	if ("910802".equals(p_req9144.reqHeader.commandCode)) {
    		return oldQrySglPay(p_req9144);
    	} else {
    		return qrySglPay(p_req9144);
    	}
    }
    
    public RetAtsSingle oldQrySglPay(ReqQrySingle p_req9144) throws Exception {
        RetAtsSingle retAts = new RetAtsSingle(p_req9144.reqHeader);
        RetAtsSglDetail tmpRetDetail = new RetAtsSglDetail();
        tmpRetDetail.reqSeqID = p_req9144.askNumber;

        try {
        	ActSetItem actItem = getBankConfig().getActSetItem(p_req9144.recAct, "");
			if (actItem == null) {
				tmpRetDetail.respCode = "0";
				tmpRetDetail.respInfo = "未找到账号[" + p_req9144.recAct + "]批量商户配置信息";
				retAts.writeRetDetail(tmpRetDetail);
				return retAts;
			} 
			
			getSessionKey(actItem);
			
			XmlTextWriter xmlWriter = new XmlTextWriter();
            xmlWriter.writeStartDocByDeclaration("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
            xmlWriter.writeStartElement("Message");
            xmlWriter.writeStartElement("Head");
            xmlWriter.writeElementString("TransCode", "02");
            xmlWriter.writeElementString("CorpNo", actItem.corpCode);
            xmlWriter.writeElementString("FeeNo", actItem.busCode);
            xmlWriter.writeEndElement();
            xmlWriter.writeStartElement("Body");
            xmlWriter.writeElementString("TransDate", Format.Date8Format.format(p_req9144.getBgnDateTime()));
            xmlWriter.writeElementString("SerialNo", p_req9144.askNumber);
            xmlWriter.writeElementString("SysSeqNo", "");
            xmlWriter.writeEndDocument();
            String xmlPck = xmlWriter.toXmlString();
            WriteBankLogStep2("发送的明文：" + xmlPck);

            String sessionKey = bankFront.customMap.get("authForRec-sessionKey");
            byte[] bytesToSend = SecurityAES.encrypt(xmlPck, sessionKey);

            String strToSend = StringHelper.bytesToHexString(bytesToSend);
            xmlWriter = null;
            xmlWriter = new XmlTextWriter();
            xmlWriter.writeStartDocByDeclaration("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
            xmlWriter.writeStartElement("Message");
            xmlWriter.writeStartElement("Head");
            xmlWriter.writeElementString("CorpNo", actItem.corpCode);
            xmlWriter.writeElementString("Version", "1.0");
            xmlWriter.writeElementString("ReqTime", bankFront.customMap.get("authForRec-timeStr"));
            xmlWriter.writeEndElement();
            xmlWriter.writeStartElement("Body");
            xmlWriter.writeElementString("ReqData", strToSend);
            xmlWriter.writeEndDocument();

            String pckSend = xmlWriter.toXmlString();

            WriteBankLogStep2("发送的密文：" + pckSend);
            byte[] result = sentBytesToBank(pckSend.getBytes(getCharset("authForRec")));
            
            String resultXml = new String(result);
            WriteBankLogStep3("接收的密文：" + resultXml);
            String xmlContent = XMLGetValueHelper.getInstance(resultXml).getString("ResData");

            xmlContent = SecurityAES.decrypt(StringUtils.hexStringToBytes(xmlContent), sessionKey);
            WriteBankLogStep3("接收的明文：" + xmlContent);

            int idxEnd = xmlContent.indexOf("</Message>");
            if (idxEnd > 0) {
                xmlContent = xmlContent.substring(0, idxEnd + 10);
            }
            XMLGetValueHelper xmlHelper = XMLGetValueHelper.getInstance(xmlContent);
            String ReturnCode = xmlHelper.getString("ReturnCode");
            String ReturnMsg = xmlHelper.getString("ReturnMsg");
            String SignStatus = xmlHelper.getString("Status");
            
            tmpRetDetail.respCode = "0";
            tmpRetDetail.respInfo = ReturnMsg;
            tmpRetDetail.transState = "0+" + SignStatus;
            tmpRetDetail.payInfoCode = ReturnCode;
        } catch (Exception ex) {
        	ex.printStackTrace();
            tmpRetDetail.respCode = "-1";
            tmpRetDetail.respInfo = ex.getMessage();
            WriteBankLogLn(ex);
        }

        retAts.writeRetDetail(tmpRetDetail);
        return retAts;
    }

    public RetAtsSingle qrySglPay(ReqQrySingle p_req) throws Exception {
        //返回ATS的对象
        RetAtsSingle retAts = new RetAtsSingle(p_req.reqHeader);
        RetAtsSglDetail tmpRetDetail = new RetAtsSglDetail();
        tmpRetDetail.reqSeqID = p_req.askNumber;

        try {
            SPDB01Header tmpBnkHeader = new SPDB01Header();
            tmpBnkHeader.transCode = "AQ50";
            XmlTextWriter xmlWriter = new XmlTextWriter();//发银行报文的XML对象
            xmlWriter.autoFormat = false;
            xmlWriter.writeStartElement("body");
            
            String ownAct = p_req.recAct;
            if ("6944".equals(p_req.reqHeader.transType)) {
            	ownAct = p_req.payAct;
            }
            xmlWriter.writeElementString("transMasterID", getBankConfig().getMapValueByKey("transMasterIDMapping", ownAct));//交易客户号
            xmlWriter.writeElementString("projectNumber", getBankConfig().getMapValueByKey("projectNumberMapping", ownAct));//项目编码
            xmlWriter.writeElementString("costItemCode", getBankConfig().getMapValueByKey("costItemCodeMapping", ownAct));//费项编码Y
            xmlWriter.writeElementString("originalTransDate", Format.Date8Format.format(p_req.getBgnDateTime()));//原交易日期
            xmlWriter.writeElementString("elecChequeNo", p_req.askNumber);//电子凭证号  查�批次�
            xmlWriter.writeElementClosed("originalPayChannelJnl"); //AQ49交易发起时输出的支付渠道流水号
            xmlWriter.writeElementClosed("handleSeqNo");//与电子凭证号二者必输其一为AQ49交易发起时输出的受理编号，即系统流水号
            xmlWriter.writeEndDocument();

            String[] tmpRetBkStr = sendToBank(xmlWriter.toXmlString(), tmpBnkHeader);
            
            if (tmpRetBkStr[0].length() == 0) {
                StringBuilder tmpSbMsg = new StringBuilder();
                XmlTextReader tmpBkReader = loadBankRespXmlReader(tmpRetBkStr[1], tmpSbMsg);
                if (tmpBkReader != null) {
                    String returnCode = tmpBkReader.getFirstText("/packet/head/returnCode");
                    String returnMsg = tmpBkReader.getFirstText("/packet/head/returnMsg");
                    tmpRetDetail.respCode = "0";
                    if (StringHelper.isNullOrEmpty(returnMsg)) {
                        returnMsg = tmpBkReader.getFirstText("/packet/body/returnMsg");
                    }
                    if ("AAAAAAA".equals(returnCode)) {
                        String handleResult = tmpBkReader.getFirstText("/packet/body/handleResult");
                        String failureMsg = tmpBkReader.getFirstText("/packet/body/failureMsg");

                        tmpRetDetail.transState = returnCode + "+" + handleResult;
                        tmpRetDetail.respInfo =  failureMsg;
                        tmpRetDetail.payInfoCode = tmpRetDetail.transState;
                        if ("1".equals(handleResult)) {
                            tmpRetDetail.payInfoCode = failureMsg;
                        }
                        if (tmpRetDetail.respInfo==null||"".equals(tmpRetDetail.respInfo)) {
                            if ("0".equals(handleResult)) {
                                tmpRetDetail.respInfo = "交易成功";
                            } else if("2".equals(handleResult)){
                                tmpRetDetail.respInfo = "提交支付中";
                            }
                        }
                    } else {
                    	if ("DSF3433".equals(returnCode) && returnMsg.contains("无指定的交易记录")) {
                    		if (canBeNotExist(p_req, tmpRetDetail, 50)) {
                    			tmpRetDetail.respCode = "0";
                    			tmpRetDetail.respInfo = returnMsg;
                    			tmpRetDetail.transState = returnCode + "+" + returnMsg;
                    			tmpRetDetail.payInfoCode = returnMsg;
                    		}
                    	} else {
                    		tmpRetDetail.respCode = "-1";
                            tmpRetDetail.respInfo = returnMsg;
                    	}
                    }
                } else {
                    tmpRetDetail.respCode = "-1";
                    tmpRetDetail.respInfo = tmpSbMsg.toString();
                }
            } else {
                tmpRetDetail.respCode = "-1";
                tmpRetDetail.respInfo = tmpRetBkStr[1];
            }
        } catch (Exception ex) {
        	ex.printStackTrace();
            tmpRetDetail.respCode = "-1";
            tmpRetDetail.respInfo = ex.getMessage();
            WriteBankLogLn(ex);
        }

        retAts.writeRetDetail(tmpRetDetail);
        return retAts;
    }
}